home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1992 June: ROMin Holiday / ADC Developer CD (1992-06) (''ROMin Holiday'')_iso / Developer Connection - 06-1992.iso / Periodicals / develop / develop 6 code / TCP / finger / TCPRoutines.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-03  |  12.7 KB  |  525 lines  |  [TEXT/MPS ]

  1. /*----------------------------------------------------------
  2. #
  3. #    finger -- MPW Tool
  4. #
  5. #    Written by Steven Falkenburg
  6. #
  7. #-----------------------------------------------------------
  8. #
  9. #    tcproutines.c
  10. #
  11. #    This code segment contains the low-level interfaces to
  12. #    the MacTCP device driver calls.
  13. #
  14. #-----------------------------------------------------------*/
  15.  
  16. #include "compat.h"
  17.  
  18. #ifdef    PROTOS
  19. #include <SysEqu.h>
  20. #include <Types.h>
  21. #include <Events.h>
  22. #include <OSUtils.h>
  23. #include <Devices.h>
  24. #include <CursorCtl.h>
  25. #include <Memory.h>
  26. #include <Dialogs.h>
  27. #include <Lists.h>
  28. #endif
  29.  
  30. #include "MacTCPCommonTypes.h"
  31. #include "TCPPB.h"
  32. #include "GetMyIPAddr.h"
  33. #include "TCPRoutines.h"
  34.  
  35. OSErr NewBlock(TCPiopb **pBlock);
  36.  
  37. const long cSleepTime = 20;
  38.  
  39. /* global variables */
  40.  
  41. extern Boolean gCancel;
  42. short         refNum;
  43.  
  44.  
  45. /* Opens the MacTCP driver.
  46.    This routine must be called prior to any of the below functions. */
  47.  
  48. OSErr OpenTCPDriver()
  49. {
  50.     OSErr    err;
  51.     
  52.     err = OpenDriver("\p.IPP",&refNum);
  53.     return(err);
  54. }
  55.  
  56.  
  57. OSErr NewBlock(TCPiopb **pBlock)
  58. {
  59.     *pBlock = (TCPiopb *)NewPtr(sizeof(TCPiopb));
  60.     if (MemError() != noErr)
  61.         return MemError();
  62.     (*pBlock)->ioCompletion = 0L;
  63.     (*pBlock)->ioCRefNum = refNum;
  64.     return noErr;
  65. }
  66.  
  67.  
  68. /* kills any pending calls to the TCP driver */
  69.  
  70. OSErr LowKillTCP(TCPiopb *pBlock)
  71. {
  72.     return(PBKillIO((ParmBlkPtr)pBlock,false));
  73. }
  74.  
  75.  
  76. /* Creates a new TCP stream in preparation for initiating a connection.
  77.    A buffer must be provided for storing incoming data waiting to be processed */
  78.  
  79. OSErr LowTCPCreateStream(StreamPtr *streamPtr,Ptr connectionBuffer,
  80.             unsigned long connBufferLen,TCPNotifyProc notifPtr)
  81. {
  82.     OSErr err;
  83.     TCPiopb *pBlock;
  84.     
  85.     if ((err = NewBlock(&pBlock)) != noErr)
  86.         return err;
  87.         
  88.     pBlock->csCode = TCPCreate;
  89.     pBlock->ioResult = 1;
  90.     pBlock->csParam.create.rcvBuff = connectionBuffer;
  91.     pBlock->csParam.create.rcvBuffLen = connBufferLen;
  92.     pBlock->csParam.create.notifyProc = notifPtr;
  93.     PBControl((ParmBlkPtr)pBlock,true);
  94.     while (pBlock->ioResult > 0 && GiveTime(cSleepTime))
  95.         ;
  96.     if (gCancel)
  97.         return -1;
  98.         
  99.     *streamPtr = pBlock->tcpStream;
  100.     err = pBlock->ioResult;
  101.     DisposPtr((Ptr)pBlock);
  102.     return err;
  103. }
  104.  
  105.  
  106. /* If TCPWaitForConnection is called asynchronously, this command retrieves the 
  107.    result of the call.  It should be called when the above command completes. */
  108.  
  109. OSErr LowFinishTCPWaitForConn(TCPiopb *pBlock,ip_addr *remoteHost,tcp_port *remotePort,
  110.                             ip_addr *localHost,tcp_port *localPort)
  111. {    
  112.     OSErr err;
  113.     
  114.     *remoteHost = pBlock->csParam.open.remoteHost;
  115.     *remotePort = pBlock->csParam.open.remotePort;
  116.     *localHost = pBlock->csParam.open.localHost;
  117.     *localPort = pBlock->csParam.open.localPort;
  118.     err = pBlock->ioResult;
  119.     DisposPtr((Ptr)pBlock);
  120.     return err;
  121. }
  122.  
  123.  
  124. /* Waits for a connection to be opened on a specified port from a specified address.
  125.    It completes when a connection is made, or a timeout value is reached.  This call
  126.    may be made asynchronously. */
  127.  
  128. OSErr LowTCPWaitForConnection(StreamPtr streamPtr,byte timeout,ip_addr *remoteHost,
  129.             tcp_port *remotePort,ip_addr *localHost,tcp_port *localPort,
  130.             Boolean async,TCPiopb **returnBlock)
  131. {
  132.     OSErr err;
  133.     TCPiopb *pBlock;
  134.     
  135.     if ((err = NewBlock(&pBlock)) != noErr)
  136.         return err;
  137.     
  138.     pBlock->csCode = TCPPassiveOpen;
  139.     pBlock->ioResult = 1;
  140.     pBlock->ioCompletion = nil;
  141.     pBlock->tcpStream = streamPtr;
  142.     pBlock->csParam.open.ulpTimeoutValue = timeout;
  143.     pBlock->csParam.open.ulpTimeoutAction = 1;
  144.     pBlock->csParam.open.validityFlags = 0xC0;
  145.     pBlock->csParam.open.commandTimeoutValue = timeout;
  146.     pBlock->csParam.open.remoteHost = *remoteHost;
  147.     pBlock->csParam.open.remotePort = *remotePort;
  148.     pBlock->csParam.open.localPort = *localPort;
  149.     pBlock->csParam.open.tosFlags = 0;
  150.     pBlock->csParam.open.precedence = 0;
  151.     pBlock->csParam.open.dontFrag = 0;
  152.     pBlock->csParam.open.timeToLive = 0;
  153.     pBlock->csParam.open.security = 0;
  154.     pBlock->csParam.open.optionCnt = 0;
  155.     PBControl((ParmBlkPtr)pBlock,true);
  156.     if (!async) {
  157.         while (pBlock->ioResult > 0 && GiveTime(cSleepTime))
  158.             ;
  159.         if (gCancel)
  160.             return -1;
  161.         return(LowFinishTCPWaitForConn(pBlock,remoteHost,remotePort,localHost,localPort));
  162.     }
  163.     
  164.     *returnBlock = pBlock;
  165.     return noErr;
  166. }
  167.  
  168.  
  169. /* Attempts to initiate a connection with a host specified by host and port. */
  170.  
  171. OSErr LowTCPOpenConnection(StreamPtr streamPtr,byte timeout,ip_addr remoteHost,
  172.             tcp_port remotePort,ip_addr *localHost,tcp_port *localPort)
  173. {
  174.     OSErr err;
  175.     TCPiopb *pBlock;
  176.     
  177.     if ((err = NewBlock(&pBlock)) != noErr)
  178.         return err;
  179.     
  180.     pBlock->csCode = TCPActiveOpen;
  181.     pBlock->ioResult = 1;
  182.     pBlock->tcpStream = streamPtr;
  183.     pBlock->csParam.open.ulpTimeoutValue = timeout;
  184.     pBlock->csParam.open.ulpTimeoutAction = 1;
  185.     pBlock->csParam.open.validityFlags = 0xC0;
  186.     pBlock->csParam.open.commandTimeoutValue = timeout;
  187.     pBlock->csParam.open.remoteHost = remoteHost;
  188.     pBlock->csParam.open.remotePort = remotePort;
  189.     pBlock->csParam.open.localPort = *localPort;
  190.     pBlock->csParam.open.tosFlags = 0;
  191.     pBlock->csParam.open.precedence = 0;
  192.     pBlock->csParam.open.dontFrag = 0;
  193.     pBlock->csParam.open.timeToLive = 0;
  194.     pBlock->csParam.open.security = 0;
  195.     pBlock->csParam.open.optionCnt = 0;
  196.     PBControl((ParmBlkPtr)pBlock,true);
  197.     while (pBlock->ioResult > 0 && GiveTime(cSleepTime))
  198.         ;
  199.     if (gCancel)
  200.         return -1;
  201.     *localHost = pBlock->csParam.open.localHost;
  202.     *localPort = pBlock->csParam.open.localPort;
  203.     err = pBlock->ioResult;
  204.     DisposPtr((Ptr)pBlock);
  205.     return err;
  206. }
  207.  
  208.  
  209. /* This routine should be called when a TCPSendData call completes.  It returns the
  210.    error code generated upon completion of the CallTCPSend. */
  211.  
  212. OSErr LowFinishTCPSend(TCPiopb *pBlock)
  213. {
  214.     OSErr err;
  215.     
  216.     err = pBlock->ioResult;
  217.     DisposPtr((Ptr)pBlock);
  218.     return err;
  219. }
  220.  
  221.  
  222. /* Sends data through an open connection stream.  Note that the connection must be
  223.    open before any data is sent. This call may be made asynchronously. */
  224.  
  225. OSErr LowTCPSendData(StreamPtr streamPtr,byte timeout,Boolean push,Boolean urgent,
  226.                     Ptr wdsPtr,Boolean async,TCPiopb **returnBlock)
  227. {    
  228.     OSErr err;
  229.     TCPiopb *pBlock;
  230.     
  231.     if ((err = NewBlock(&pBlock)) != noErr)
  232.         return err;
  233.     
  234.     pBlock->csCode = TCPSend;
  235.     pBlock->ioResult = 1;
  236.     pBlock->tcpStream = streamPtr;
  237.     pBlock->ioCompletion = nil;
  238.     pBlock->csParam.send.ulpTimeoutValue = timeout;
  239.     pBlock->csParam.send.ulpTimeoutAction = 1;
  240.     pBlock->csParam.send.validityFlags = 0xC0;
  241.     pBlock->csParam.send.pushFlag = push;
  242.     pBlock->csParam.send.urgentFlag = urgent;
  243.     pBlock->csParam.send.wdsPtr = wdsPtr;
  244.     PBControl((ParmBlkPtr)pBlock,true);
  245.     if (!async) {
  246.         while (pBlock->ioResult > 0 && GiveTime(cSleepTime))
  247.             ;
  248.         if (gCancel)
  249.             return -1;
  250.         return LowFinishTCPSend(pBlock);
  251.         return err;
  252.     }
  253.     
  254.     *returnBlock = pBlock;
  255.     return noErr;
  256. }
  257.  
  258.  
  259. OSErr LowFinishTCPNoCopyRcv(TCPiopb *pBlock,Boolean *urgent,Boolean *mark)
  260. {
  261.     OSErr err;
  262.     
  263.     *urgent = pBlock->csParam.receive.urgentFlag;
  264.     *mark = pBlock->csParam.receive.markFlag;
  265.     
  266.     err = pBlock->ioResult;
  267.     DisposPtr((Ptr)pBlock);
  268.     return err;
  269. }
  270.  
  271.  
  272. OSErr LowTCPNoCopyRcv(StreamPtr streamPtr,byte timeout,Boolean *urgent,Boolean *mark,
  273.                 Ptr rdsPtr,short numEntry,Boolean async,TCPiopb **returnBlock)
  274. {
  275.     OSErr    err = noErr;
  276.     TCPiopb *pBlock;
  277.     
  278.     if ((err = NewBlock(&pBlock)) != noErr)
  279.         return err;
  280.     
  281.     pBlock->csCode = TCPNoCopyRcv;
  282.     pBlock->ioResult = 1;
  283.     pBlock->tcpStream = streamPtr;
  284.     pBlock->ioCompletion = nil;
  285.     pBlock->csParam.receive.commandTimeoutValue = timeout;
  286.     pBlock->csParam.receive.rdsPtr = rdsPtr;
  287.     pBlock->csParam.receive.rdsLength = numEntry;
  288.     PBControl((ParmBlkPtr)pBlock,true);
  289.     if (!async) {
  290.         while (pBlock->ioResult > 0 && GiveTime(cSleepTime))
  291.             ;
  292.         if (gCancel)
  293.             return -1;
  294.         return LowFinishTCPNoCopyRcv(pBlock,urgent,mark);
  295.     }
  296.     
  297.     *returnBlock = pBlock;
  298.     return noErr;
  299. }
  300.  
  301.  
  302. OSErr LowTCPBfrReturn(StreamPtr streamPtr,Ptr rdsPtr)
  303. {
  304.     OSErr err;
  305.     TCPiopb *pBlock;
  306.     
  307.     if ((err = NewBlock(&pBlock)) != noErr)
  308.         return err;
  309.     
  310.     pBlock->csCode = TCPRcvBfrReturn;
  311.     pBlock->ioResult = 1;
  312.     pBlock->tcpStream = streamPtr;
  313.     pBlock->csParam.receive.rdsPtr = rdsPtr;
  314.     PBControl((ParmBlkPtr)pBlock,true);
  315.     while (pBlock->ioResult > 0 && GiveTime(cSleepTime))
  316.         ;
  317.     if (gCancel)
  318.         return -1;
  319.     err = pBlock->ioResult;
  320.     DisposPtr((Ptr)pBlock);
  321.     return err;
  322. }
  323.  
  324.  
  325. /* If the above is called asynchronously, this routine returns the data that was
  326.    received from the remote host. */
  327.    
  328. OSErr LowFinishTCPRecv(TCPiopb *pBlock,Boolean *urgent,Boolean *mark,
  329.                     unsigned short *rcvLen)
  330. {
  331.     OSErr err;
  332.     
  333.     *rcvLen = pBlock->csParam.receive.rcvBuffLen;
  334.     *urgent = pBlock->csParam.receive.urgentFlag;
  335.     *mark = pBlock->csParam.receive.markFlag;
  336.     err = pBlock->ioResult;
  337.     DisposPtr((Ptr)pBlock);
  338.     return err;
  339. }
  340.  
  341.  
  342. /* Attempts to pull data out of the incoming stream for a connection. If data is
  343.    not present, the routine waits a specified amout of time before returning with
  344.    a timeout error.  This call may be made asynchronously. */
  345.    
  346. OSErr LowTCPRecvData(StreamPtr streamPtr,byte timeout,Boolean *urgent,Boolean *mark,
  347.                 Ptr rcvBuff,unsigned short *rcvLen,Boolean async,TCPiopb **returnBlock)
  348. {
  349.     OSErr err;
  350.     TCPiopb *pBlock;
  351.     
  352.     if ((err = NewBlock(&pBlock)) != noErr)
  353.         return err;
  354.     
  355.     pBlock->csCode = TCPRcv;
  356.     pBlock->ioResult = 1;
  357.     pBlock->ioCompletion = nil;
  358.     pBlock->tcpStream = streamPtr;
  359.     pBlock->csParam.receive.commandTimeoutValue = timeout;
  360.     pBlock->csParam.receive.rcvBuff = rcvBuff;
  361.     pBlock->csParam.receive.rcvBuffLen = *rcvLen;
  362.     PBControl((ParmBlkPtr)pBlock,true);
  363.     if (!async) {
  364.         while (pBlock->ioResult > 0 && GiveTime(cSleepTime))
  365.             ;
  366.         if (gCancel)
  367.             return -1;
  368.         return(LowFinishTCPRecv(pBlock,urgent,mark,rcvLen));
  369.     }
  370.     
  371.     *returnBlock = pBlock;
  372.     return noErr;
  373. }
  374.     
  375.  
  376. /* Gracefully closes a connection with a remote host.  This is not always possible,
  377.    and the programmer might have to resort to CallTCPAbort, described next. */
  378.  
  379. OSErr LowTCPClose(StreamPtr streamPtr,byte timeout)
  380. {
  381.     OSErr err;
  382.     TCPiopb *pBlock;
  383.     
  384.     if ((err = NewBlock(&pBlock)) != noErr)
  385.         return err;
  386.     
  387.     pBlock->csCode = TCPClose;
  388.     pBlock->ioResult = 1;
  389.     pBlock->tcpStream = streamPtr;
  390.     pBlock->csParam.close.ulpTimeoutValue = timeout;
  391.     pBlock->csParam.close.validityFlags = 0xC0;
  392.     pBlock->csParam.close.ulpTimeoutAction = 1;
  393.     PBControl((ParmBlkPtr)pBlock,true);
  394.     while (pBlock->ioResult > 0 && GiveTime(cSleepTime))
  395.         ;
  396.     if (gCancel)
  397.         return -1;
  398.     err = pBlock->ioResult;
  399.     DisposPtr((Ptr)pBlock);
  400.     return err;
  401. }
  402.  
  403.  
  404. /* Should be called if a CallTCPClose fails to close a connection properly.
  405.    This call should not normally be used to terminate connections. */
  406.    
  407. OSErr LowTCPAbort(StreamPtr streamPtr)
  408. {
  409.     OSErr err;
  410.     TCPiopb *pBlock;
  411.     
  412.     if ((err = NewBlock(&pBlock)) != noErr)
  413.         return err;
  414.     
  415.     pBlock->csCode = TCPAbort;
  416.     pBlock->ioResult = 1;
  417.     pBlock->tcpStream = streamPtr;
  418.     PBControl((ParmBlkPtr)pBlock,true);
  419.     while (pBlock->ioResult > 0 && GiveTime(cSleepTime))
  420.         ;
  421.     if (gCancel)
  422.         return -1;
  423.     err = pBlock->ioResult;
  424.     DisposPtr((Ptr)pBlock);
  425.     return err;
  426. }
  427.  
  428. OSErr LowTCPStatus(StreamPtr streamPtr,TCPStatusPB *theStatus)
  429. {
  430.     OSErr err;
  431.     TCPiopb *pBlock;
  432.     
  433.     if ((err = NewBlock(&pBlock)) != noErr)
  434.         return err;
  435.     
  436.     pBlock->csCode = TCPStatus;
  437.     pBlock->ioResult = 1;
  438.     pBlock->tcpStream = streamPtr;
  439.     PBControl((ParmBlkPtr)pBlock,true);
  440.     while (pBlock->ioResult > 0 && GiveTime(cSleepTime))
  441.         ;
  442.     if (gCancel)
  443.         return -1;
  444.     theStatus = &(pBlock->csParam.status);
  445.     err = pBlock->ioResult;
  446.     DisposPtr((Ptr)pBlock);
  447.     return err;
  448. }
  449.  
  450.  
  451. /* Deallocates internal buffers used to hold connection data. This should be
  452.    called after a connection has been closed. */
  453.  
  454. OSErr LowTCPRelease(StreamPtr streamPtr,Ptr *recvPtr,unsigned long *recvLen)
  455. {
  456.     OSErr err;
  457.     TCPiopb *pBlock;
  458.     
  459.     if ((err = NewBlock(&pBlock)) != noErr)
  460.         return err;
  461.     
  462.     pBlock->csCode = TCPRelease;
  463.     pBlock->ioResult = 1;
  464.     pBlock->tcpStream = streamPtr;
  465.     PBControl((ParmBlkPtr)pBlock,true);
  466.     while (pBlock->ioResult > 0 && GiveTime(cSleepTime))
  467.         ;
  468.     if (gCancel)
  469.         return -1;
  470.     *recvPtr = pBlock->csParam.create.rcvBuff;
  471.     *recvLen = pBlock->csParam.create.rcvBuffLen;
  472.     err = pBlock->ioResult;
  473.     DisposPtr((Ptr)pBlock);
  474.     return err;
  475. }
  476.  
  477. OSErr LowTCPGlobalInfo(Ptr *tcpParam,Ptr *tcpStat)
  478. {
  479.     OSErr err;
  480.     TCPiopb *pBlock;
  481.     
  482.     if ((err = NewBlock(&pBlock)) != noErr)
  483.         return err;
  484.     
  485.     pBlock->csCode = TCPGlobalInfo;
  486.     pBlock->ioResult = 1;
  487.     PBControl((ParmBlkPtr)pBlock,true);
  488.     while (pBlock->ioResult > 0 && GiveTime(cSleepTime))
  489.         ;
  490.     if (gCancel)
  491.         return -1;
  492.     *tcpParam = (Ptr) pBlock->csParam.globalInfo.tcpParamPtr;
  493.     *tcpStat = (Ptr) pBlock->csParam.globalInfo.tcpStatsPtr;
  494.     err = pBlock->ioResult;
  495.     DisposPtr((Ptr)pBlock);
  496.     return err;
  497. }
  498.  
  499.  
  500. /* Returns the IP address of the local computer. */
  501.  
  502. OSErr GetMyIP(ip_addr *ipnum)
  503. {
  504.     struct    IPParamBlock    *IPBlock;
  505.     OSErr    err;
  506.     
  507.     IPBlock = (struct IPParamBlock *)NewPtr(sizeof(struct IPParamBlock));
  508.     if (MemError() != noErr)
  509.         return MemError();
  510.     
  511.     IPBlock->ioResult = 1;
  512.     IPBlock->csCode = ipctlGetAddr;
  513.     IPBlock->ioCompletion = nil;
  514.     IPBlock->ioCRefNum = refNum;
  515.     PBControl((ParmBlkPtr)IPBlock,true);
  516.     while (IPBlock->ioResult > 0 && GiveTime(cSleepTime))
  517.         ;
  518.     if (gCancel)
  519.         return -1;
  520.     *ipnum = IPBlock->ourAddress;
  521.     err = IPBlock->ioResult;
  522.     DisposPtr((Ptr)IPBlock);
  523.     return err;
  524. }
  525.